
#include "native_stack.h"
#include "native_array.h"
#include "raise.h"
#include "new.h"


BEGIN_CLASS(NativeStack);
    size_t _elem_size;
    size_t _index;
    Object* _array;
END_CLASS(NativeStack);


static void NativeStack_ctor(NativeStackClass* this, va_list* ap)
{
    this->_elem_size = va_arg(*ap, size_t);
    this->_array = incref(new(NativeArray, 0, this->_elem_size));
}

static void NativeStack_dtor(NativeStackClass* this)
{
    decref(this->_array);
}

static char const* NativeStack_str(NativeStackClass* this)
{
    return str(this->_array);
}

static void NativeStack_push(NativeStackClass* this, va_list* ap)
{
    switch (this->_elem_size)
    {
    case 1:
    case 2:
    case 4:
        setitem(this->_array, this->_index, va_arg(*ap, int32_t));
        break;
    case 8:
        setitem(this->_array, this->_index, va_arg(*ap, int64_t));
        break;
    default:
        raise("Size not valid");
    }
    this->_index++;
}

static void NativeStack_pop(NativeStackClass* this)
{
    if (this->_index == 0)
        raise("Stack is empty, cannot pop");
    this->_index--;
}

static Object* NativeStack_top(NativeStackClass* this)
{
    if (this->_index == 0)
        raise("Stack is empty, cannot get top");
    return getitem(this->_array, this->_index - 1);
}

static size_t NativeStack_size(NativeStackClass const* this)
{
    return this->_index;
}

IMPL_CONTAINER_CLASS(
    NativeStack,
    &NativeStack_ctor, &NativeStack_dtor, &NativeStack_str,
    NULL, NULL, NULL, NULL,
    NULL, NULL, NULL, // eq, gt, lt
    &NativeStack_push, //push_front
    &NativeStack_push,
    &NativeStack_pop, // pop_front
    &NativeStack_pop,
    NULL, //append
    NULL, //erase
    NULL, //clear
    &NativeStack_top, // front
    &NativeStack_top, // back
    &NativeStack_size,
    NULL, //setitem,
    NULL, //getitem,
    NULL, // begin
    NULL, // end

    0, // _elem_size
    0, // _index
    NULL    // _str
);




